import json
import traceback
from . import constants as c
from threading import Thread

class Client:
    """    客户端与服务端网络交互相关的操作    """

    def __init__(self, socket):
        self.socket = socket  # 客户端socket
        # 创建一个线程专门处理数据接收
        thread = Thread(target=self.recv_data)
        thread.setDaemon(True)
        thread.start()

        self.login_state = 0
        self.reg_state = 0
        self.join_state = 0
        self.round = 0
        self.win_state = False
        self.player_name = None
        self.opponent_name = None
        self.map = None
        self.renew_data = None

    def data_handler(self):
        # 给每个连接创建一个独立的线程进行管理
        thread = Thread(target=self.recv_data)
        thread.setDaemon(True)
        thread.start()

    def deal_data(self, bytes):
        """        处理数据        """
        # 将字节流转成字符串
        pck = bytes.decode()
        # 切割数据包
        pck = pck.split('|#|')
        # 处理每一个协议,最后一个是空字符串，不用处理它
        for str_protocol in pck[:-1]:
            protocol = json.loads(str_protocol)
            # 根据协议中的protocol字段，直接调用相应的函数处理
            self.protocol_handler(protocol)

    def recv_data(self):
        # 接收数据
        try:
            while True:
                bytes = self.socket.recv(4096)
                if len(bytes) == 0:
                    self.socket.close()
                    # TODO:掉线处理
                    break
                # 处理数据
                self.deal_data(bytes)
        except:
            self.socket.close()
            # TODO:异常掉线处理
            traceback.print_exc()

    def send(self, py_obj):
        """        给服务器发送协议包        py_obj:python的字典或者list        """
        self.socket.sendall((json.dumps(py_obj, ensure_ascii=False) + '|#|').encode())

    def protocol_handler(self, protocol):
        """   处理服务端发来的协议    """
        print('正在处理' + protocol.get('protocol') + '协议')


        if protocol['protocol'] == 'ser_login':
            # 登录协议的相关逻辑
            if not protocol['result']:
                self.login_state = -1
                c.G_LOGINSTATE = False
                return
            # 登录成功
            self.login_state = 1
            c.G_LOGINSTATE = True
            self.player_name = protocol['username']

        elif protocol['protocol'] == 'ser_reg':
            if not protocol['result']:
                self.reg_state = -1
                c.G_LOGINSTATE = False
                return
            # 注册成功
            self.reg_state = 1
            c.G_LOGINSTATE = True
            self.player_name = protocol['username']

            self.append_player(self.player_name)

            return

        elif protocol['protocol'] == 'ser_load':
            self.round = protocol['round']
            self.map = protocol['map']
            c.G_CLIENT = self
            return

        elif protocol['protocol'] == 'ser_newgame':
            game_id = protocol['game_id']
            self.writedict_info(self.player_name, game_id, 2, 'none', c.G_ACTIVEBOX)
            # 写入player_info
            return

        elif protocol['protocol'] == 'ser_join':
            if not protocol['result']:
                self.join_state = -1
                return
            # 加入成功
            self.join_state = 1
            oppo_name = protocol['opponent_data']
            game_id = protocol['game_id']

            self.writedict_info(self.player_name, game_id, 1, oppo_name, c.G_ACTIVEBOX)
            self.writeoppo_info(oppo_name, game_id, self.player_name)
            return

        elif protocol['protocol'] == 'ser_renew':
            self.renew_data = protocol['result']
            return

        elif protocol['protocol'] == 'ser_win':
            self.win_state = True
            name = self.findplayer(self.player_name)
            x = name['win_num']
            self.writedict_num(self.player_name, x + 1)
            self.writedict_info(self.player_name, 0, 0, 'none', c.G_ACTIVEBOX)

    def login(self, usrn, pswd):
        """        登录        """
        data = {
            'protocol': 'cli_login',
            'username': usrn,
            'password': pswd
        }
        self.send(data)

    def register(self, usrn, pswd, nknm):
        data = {
            'protocol': 'cli_reg',
            'username': usrn,
            'password': pswd,
            'nickname': nknm
        }
        self.send(data)

    def load(self, player_name, game_id):
        data = {
            'protocol': 'cli_load',
            'game_id': game_id
        }
        player = self.findplayer(player_name)
        for game in player['game_info']:
            if game['game_id'] == game_id:
                break
        self.opponent_name = game['opponent_name']
        self.send(data)

    def renew(self, game_ids):
        data = {
            'protocol': 'cli_renew',
            'game_ids': game_ids
        }
        self.send(data)

    def upload(self, game_id, map):
        data = {
            'protocol': 'cli_upload',
            'game_id': game_id,
            'map': map
        }
        self.send(data)

    def join(self, game_id):
        data = {
            'protocol': 'cli_join',
            'game_id' : game_id
        }
        self.send(data)

    def newgame(self):
        data = {
            'protocol': 'cli_newgame'
        }
        print('to' + str(c.G_ACTIVEGAME))
        self.send(data)

    def win(self, game_id):
        data = {
            'protocol': 'cli_win',
            'game_id': game_id
        }
        self.send(data)

    def clear_data(self, box):
        self.writedict_info(self.player_name, 0, 0, 'none', box)

    def logout(self):
        # 清空所有信息
        self.send('')
        c.G_CLIENT = None
        c.G_LOGINSTATE = False
        c.G_ACTIVEGAME = None





    def load_id(self):
        player = self.findplayer(self.player_name)
        ids = []
        for game in player['game_info']:
            ids.append(game['game_id'])
        return ids

    def findplayer(self, username):
        # 查找该用户名，返回用户名信息字典
        with open('data/player_info.json', 'r', encoding="utf-8") as load_f:
            data = json.load(load_f)
            for name in data['player']:
                if name['username'] == username:
                    return name
            return None

    def writedict_num(self, username, num):
        with open('data/player_info.json', 'r+', encoding="utf-8") as load_f:
            dict = json.load(load_f)
            for name in dict['player']:
                if name['username'] == username:
                    name['win_num'] = num
                    load_f.seek(0)
                    json.dump(dict, load_f, ensure_ascii=False)
                    load_f.truncate()

    def writedict_info(self, username, id, sequence, oppo_name, game):
        # 对局初始化时 写入字典
        with open('data/player_info.json', 'r+', encoding="utf-8") as load_f:
            dict = json.load(load_f)
            for name in dict['player']:
                if name['username'] == username:
                    name['game_info'][game]['game_id'] = id
                    name['game_info'][game]['sequence'] = sequence
                    name['game_info'][game]['opponent_name'] = oppo_name
                    load_f.seek(0)
                    json.dump(dict, load_f, ensure_ascii=False)
                    load_f.truncate()

    def writeoppo_info(self, oppo_name, id, self_name):
        # 对局初始化时 写入字典
        with open('data/player_info.json', 'r+', encoding="utf-8") as load_f:
            dict = json.load(load_f)
            for name in dict['player']:
                if name['username'] == oppo_name:
                    for game in name['game_info']:
                        if game['game_id'] == id:
                            game['opponent_name'] = self_name
                            load_f.seek(0)
                            json.dump(dict, load_f, ensure_ascii=False)
                            load_f.truncate()

    def append_player(self, username):
        # 注册玩家时 写入字典
        with open('data/player_info.json', 'r+', encoding="utf-8") as load_f:
            dict = json.load(load_f)
            mydict = {}
            mydict['username'] = username
            mydict['win_num'] = 0
            info_dict = {}
            info_dict['game_id'] = 0
            info_dict['sequence'] = 0
            info_dict['opponent_name'] = 'none'
            mydict['game_info'] = [0] * 6
            for i in range(0, 6):
                mydict['game_info'][i] = info_dict

            dict['player'].append(mydict)
            load_f.seek(0)
            json.dump(dict, load_f, ensure_ascii=False)
            load_f.truncate()
